﻿using System;
using System.Collections.Generic;
using Drill.Configuration;
using Drill.Core.Utilities;

namespace Drill.Core
{
	public class ConfigBasedRootPathProviderFactory : IRootPathProviderFactory
	{
		private readonly IRootPathProviderConfigurationCollection _rootPathProviderConfigs;

		public ConfigBasedRootPathProviderFactory(IRootPathProviderConfigurationCollection rootPathProviderConfigs)
		{
			if (null == rootPathProviderConfigs)
			{
				throw new ArgumentNullException("rootPathProviderConfigs");
			}
			if (rootPathProviderConfigs.Count < 1)
			{
				throw new ArgumentException("The rootPathProviderConfigs collection is empty but it must contain at least one item.", "rootPathProviderConfigs");
			}
			_rootPathProviderConfigs = rootPathProviderConfigs;
		}

		public IList<IRootPathProvider> CreateRootPathProviders()
		{
			List<IRootPathProvider> pathProviders = new List<IRootPathProvider>(_rootPathProviderConfigs.Count);
			foreach (var rootPathProviderConfig in _rootPathProviderConfigs)
			{
				if (null == rootPathProviderConfig)
				{
					continue;
				}

				IRootPathProvider rootPathProvider = CreateFromConfig(rootPathProviderConfig);
				if (null == rootPathProvider)
				{
					continue;
				}
				pathProviders.Add(rootPathProvider);
			}
			return pathProviders;
		}

		private IRootPathProvider CreateFromConfig(IRootPathProviderConfiguration rootPathProviderConfig)
		{
			if (null == rootPathProviderConfig)
			{
				throw new ArgumentNullException("rootPathProviderConfig");
			}

			if (false == rootPathProviderConfig.Enabled)
			{
				return null;
			}

			string assemblyQualifiedTypeName = rootPathProviderConfig.Type;

			if (string.IsNullOrWhiteSpace(assemblyQualifiedTypeName))
			{
				throw new ArgumentException(
					"The rootPathProviderConfig argument's Type property cannot be null, empty or whitespace. "
				  + "It must contain the assembly-qualified type name of the root path provider implementation."
				  , "rootPathProviderConfig"
					);
			}
			return CreateFromAssemblyQualifiedTypeName(assemblyQualifiedTypeName);
		}

		private IRootPathProvider CreateFromAssemblyQualifiedTypeName(string assemblyQualifiedTypeName)
		{
			if (string.IsNullOrWhiteSpace(assemblyQualifiedTypeName))
			{
				throw new ArgumentNullException("assemblyQualifiedTypeName");
			}

			return
				AssemblyUtility.CreateInstance<IRootPathProvider>(
					assemblyQualifiedTypeName
				  , "root path provider"
				  , new object[] { }
					);
		}
	}
}